package gluck.sintactico.symbolTable;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

public class SymbolTable {

	Hashtable<NodeKey, Node> table; 
	Level level;
	FileWriter outputFile;
	String functionName;
	
	public SymbolTable ()
	{
		this.table = new Hashtable<NodeKey, Node>();
		level = new Level();
		functionName=null;
	}
	
	public void addNode(String name, String type)
	{
		Node node;
		NodeKey key;
		
		if(name==null || type==null)
		{
			//System.err.println("id or type are null values");
			return;
		}
			
		if(type.equals("function"))
		{
			key = new NodeKey("func", name);
		}
		else
		{
			key = new NodeKey(level.toString(), name);
		}
		node = new Node(key,type);
		/* Check if function is already present */
		if(table.containsKey(key))
		{			
			System.err.println("Warning: the id '"+name+"' already exist in the same block.");
			return;
		} 
								
		table.put(key, node);

		
		writeNode(node);

	}

	
	public void addFunction(String name){
		functionName=name;
	}
	
	private void writeNode(Node node) {
		int i, depth, maxlen=20;
		
		depth=level.getDepth();
		try
		{
		for(i=0;i<depth;i++)
		{
			outputFile.append(' ');
		}
		maxlen-=depth;
		
		outputFile.write(node.key.name);
		maxlen-=node.key.name.length();
		for(i=0;i<maxlen;i++)
		{
			outputFile.append(' ');
		}
		if(node.type.equals("function"))
		{
			this.outputFile.write("func                \n");
		}
		else
		{	
			this.outputFile.write("var                  ");
			
			this.outputFile.write(node.type);
		
			this.outputFile.append('\n');
		}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		
	}

	public void printTable()
	{
		Node node;

		Enumeration<Node> nodes = table.elements();
				
		while( nodes.hasMoreElements() )
		{
			node = nodes.nextElement();
			System.out.println( node.key.level+" - "+node.key.name+" - "+node.type);
		}
	}	
	
	public void startBlock()
	{
		if(functionName!=null){
			addNode(functionName, "function");
			functionName=null;
		}
		level.LevelUp();
	}
	
	public void endBlock()
	{
		level.LevelDown();
	}

	public void startFun() {
		//level.addLevel();
	}

	public void setOutput(FileWriter outputFile) {
		this.outputFile = outputFile;
		try {
			this.outputFile.write("Nombre              Funcion/Variable     Tipo de dato\n");
			this.outputFile.write("******              ****************     ************\n");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
} 
